home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 431_01 / svr0.asm < prev    next >
Assembly Source File  |  1994-06-09  |  14KB  |  572 lines

  1. ;----------------------------------------------------------------------
  2. ;----------------------------------------------------------------------
  3. ;
  4. ; this is the server - specific assembly code. 
  5. ; some notes:
  6. ;   in thought i could interrupt DOS any time outside of a DOS
  7. ;   critical area (flagged through int 2a/80 2a/81 2a/82) by simply
  8. ;   swapping the SDA. surprise! i have used this technique many times
  9. ;   in the past, but it seems that if both a background and foreground
  10. ;   process are doing directory searches, they interfere with each
  11. ;   other. that's what some of the more bizarre looking checks
  12. ;   are all about.
  13. ;
  14. ;----------------------------------------------------------------------
  15. ;----------------------------------------------------------------------
  16.  
  17. SVR0_TEXT    segment    byte public 'CODE'
  18. DGROUP    group    _DATA,_BSS
  19.     assume    cs:SVR0_TEXT,ds:DGROUP
  20. SVR0_TEXT    ends
  21.  
  22. _DATA    segment word public 'DATA'
  23. d@    label    byte
  24. d@w    label    word
  25.  
  26. STK1LEN    equ    512             ; stack while servicing any
  27. stk1    db    STK1LEN dup (0)        ; interrupt
  28. stk1end    equ    $
  29. stk1sav    dd    0
  30.  
  31. userintno    db    ?        ; communications int #
  32.  
  33. _DATA    ends
  34.  
  35. _BSS    segment word public 'BSS'
  36. b@    label    byte
  37. b@w    label    word
  38. _BSS    ends
  39.  
  40. extrn   _ServerDispatch : far
  41. extrn    _UserInt    : far
  42. extrn   _background     : byte
  43. extrn    _SDA        : far ptr
  44. extrn   _SDA_DOSBUSY    : far ptr
  45. extrn    _lcl_SDA    : far ptr
  46. extrn    _CDS_base    : far ptr
  47. extrn    _lcl_CDS    : far ptr
  48. extrn    _SDA_maxsize    : word
  49. extrn    _SDA_minsize    : word
  50. extrn    _CDS_TotalSize    : word
  51. extrn    __Recieve    : far
  52.  
  53. public  _svr0_init
  54. public  _svr0_shutdown
  55. public    _svr0_GetSemaphores
  56. public  _svr0_SetDispatchFlag
  57. public  _svr0_ResetDispatchFlag
  58. public  _svr0_GetStackUsed
  59. public    _svr0_int1b
  60. public    _svr0_int23
  61. public    _svr0_int24
  62. public    _SwapDOS
  63.  
  64. SVR0_TEXT    segment    byte public 'CODE'
  65.  
  66. ;
  67. ; these are easiest to keep in the code segment. bad
  68. ; practice though :)
  69. ;
  70. semflag        db    0        ; BIOS semaphore flags
  71. doscrit        db    0        ; DOS critical flag
  72. callsvr        db    0        ; call server pending
  73.  
  74. ;
  75. ; swap two memory regious
  76. ;   es:di --> src 1
  77. ;   ds:si --> src 2
  78. ;   cx    =   length
  79. ; exit:
  80. ;   ax = ?
  81. ;   cx = 0
  82. ;   si/di are incremented [cx] bytes
  83. ;   all others unchanged
  84. ; notes:
  85. ;   i don't check that either di or si (or both) are at even addresses.
  86. ;   this routine slows considerably if that is not the case!
  87. ;
  88. swap        proc    near
  89.         pushf
  90.         cld            ; want increment on string cmds
  91.         shr    cx,1        ; cx /= 2 (holds # of words to move)
  92.         jz    @@m1        ; if zero, skip
  93.         pushf            ; save carry flag
  94. @@ms:
  95.         mov    bx,es:[di]    ; swap 1 word at a time
  96.         movsw
  97.         mov    [si-2],bx
  98.         loop    @@ms
  99.         popf            ; get carry back
  100. @@m1:
  101.         jnc    @@mr        ; skip on no carry
  102.         mov    ah,es:[di]    ; otherwise move odd byte
  103.         movsb
  104.         mov    [si-1],ah
  105. @@mr:
  106.         popf
  107.         ret
  108. swap        endp
  109.  
  110. _SwapDOS    proc    far
  111.         push    ax
  112.         push    cx
  113.         push    di
  114.         push    si
  115.         push    es
  116.         
  117.         push    ds            ; swap SDA
  118.         mov    cx,[_SDA_maxsize]
  119.         les    di,[_SDA]
  120.         lds    si,[_lcl_SDA]
  121.         call    swap
  122.         pop    ds
  123.  
  124.         push    ds            ; swap CDS
  125.         mov    cx,[_CDS_TotalSize]
  126.         les    di,[_CDS_base]
  127.         lds    si,[_lcl_CDS]
  128.         call    swap
  129.         pop    ds
  130.         pop    es
  131.         pop    si
  132.         pop    di
  133.         pop    cx
  134.         pop    ax
  135.         ret
  136. _SwapDOS    endp
  137.  
  138. ;----------------------------------------------------------------------
  139. ; test to see if the server needs to be called (or can be called)
  140. ; and do all of the necessary prep work.
  141. ;----------------------------------------------------------------------
  142. svrhere        db    0        ; local semaphore
  143. _svr0_TestCallSvr    proc    far
  144.         pushf            ; save things as i go along...
  145.         push    ds
  146.         push    bp
  147.  
  148.         mov    bp,DGROUP
  149.         mov    ds,bp
  150.         
  151.                 cmp     DGROUP:[_background],0    ; are we a background task?
  152.                 jz      @@__svr0a        ; no, skip!
  153.         
  154.         ;
  155.         ; everything from this test until we either
  156.         ; set the flag or exit must not be interrupted!
  157.         ;
  158.         cli
  159.         cmp    cs:[svrhere],0        ; are we here?
  160.         jnz    @@__svr0a        ; yes, exit!
  161.         
  162.         cmp     cs:[semflag], 0        ; any BIOS locks?
  163.         jnz    @@__svr0a        ; yes, exit!
  164.         
  165.         cmp    cs:[doscrit],0        ; DOS in critical area?
  166.         jnz    @@__svr0a        ; yes, exit!
  167.         
  168.         push    di            ; finally, check DOS busy
  169.         push    es
  170.         les    di,[_SDA_DOSBUSY]
  171.         cmp byte ptr es:[di],0        ; if DOS not busy, OK
  172.         jz    @@_svr0_OK
  173.         cmp byte ptr es:[di],1        ; if DOS ct > 1, BAD
  174.         jnz    @@_svr0_OK
  175.         cmp    [int28here],1        ; if DOS ct IS 1
  176.                         ;   and we're at int 28
  177.                         ;   OK!
  178. @@_svr0_OK:        
  179.         pop    es
  180.         pop    di
  181.         jz    @@__svr1        ; DOS not busy, continue
  182. @@__svr0a:    
  183.         jmp    @@TestCallSvrR
  184. @@__svr1:        
  185.         mov    cs:[svrhere],1        ; set semaphore
  186.                         ; save stack
  187.         mov word ptr DGROUP:[stk1sav],sp    
  188.         mov word ptr DGROUP:[stk1sav+2],ss
  189.  
  190.         cli                ; set local stack
  191.         mov    sp, offset stk1end
  192.         mov    bp,ds
  193.         mov    ss,bp
  194.         sti
  195.         
  196.         push    ax            ; save remaining regs
  197.         push    bx
  198.         push    cx
  199.         push    dx
  200.         push    di
  201.         push    si
  202.         push    es
  203.  
  204.         call    __Recieve        ; check for recieve
  205.         cmp    cs:[callsvr],0        ; ready to call server?
  206.         jz    @@__svr0_rcv        ; no, done!
  207.         
  208.         call    _SwapDOS
  209.         call    _ServerDispatch        ; dispatch command
  210.         call    _SwapDOS
  211. @@__svr0_rcv:
  212.         pop    es
  213.         pop    si
  214.         pop    di
  215.         pop    dx
  216.         pop    cx
  217.         pop    bx
  218.         pop    ax
  219.         
  220.         cli
  221.         mov    sp,word ptr DGROUP:[stk1sav]
  222.         mov    ss,word ptr DGROUP:[stk1sav+2]
  223.         sti
  224.         mov    cs:[svrhere],0        ; reset semaphore
  225. @@TestCallSvrR:
  226.         pop    bp
  227.         pop    ds
  228.         popf
  229.         ret
  230. _svr0_TestCallSvr endp
  231.  
  232. ;----------------------------------------------------------------------
  233. ; my int 9 control-break handler (ignore)
  234. ;----------------------------------------------------------------------
  235. _svr0_int1b    proc    far
  236.         iret
  237. _svr0_int1b    endp
  238.  
  239. ;----------------------------------------------------------------------
  240. ; here is my control-break handler (ignore)
  241. ;----------------------------------------------------------------------
  242. _svr0_int23    proc    far
  243.         iret
  244. _svr0_int23    endp
  245.  
  246. ;----------------------------------------------------------------------
  247. ; my critical error handler (always return FAIL)
  248. ;----------------------------------------------------------------------
  249. _svr0_int24    proc    far
  250.         mov    al,03h
  251.         iret
  252. _svr0_int24    endp
  253.  
  254. ;----------------------------------------------------------------------
  255. ; clock int
  256. ;   we could only be here if the server was called during the last
  257. ;   timer tick, but better safe than sorry.
  258. ;----------------------------------------------------------------------
  259. int08here    db    0
  260. oldint08    dd    0
  261. semint08    proc    far
  262.         pushf                ; emulate an INT 08
  263.         call    cs:[oldint08]
  264.         cli
  265.         cmp    cs:[int08here],0    ; check semaphore
  266.         jnz    @@semint08R        ; skip if here
  267.         inc    cs:[int08here]
  268.         call    _svr0_TestCallSvr    ; try me
  269.         dec    cs:[int08here]
  270. @@semint08R:        
  271.         iret                ; finished
  272. semint08    endp
  273.  
  274. ;----------------------------------------------------------------------
  275. ; don't interrupt a disk action
  276. ;----------------------------------------------------------------------
  277. oldint13    dd    0
  278. semint13    proc    far
  279.         inc    cs:[semflag]
  280.         pushf
  281.         call     cs:[oldint13]
  282.         pushf
  283.         dec    cs:[semflag]
  284.         jnz    @@__int13a
  285.         call    _svr0_TestCallSvr
  286. @@__int13a:        
  287.         popf
  288.         retf    2            ; pop old flags
  289. semint13    endp
  290.  
  291. ;----------------------------------------------------------------------
  292. ; forward call calls to DOS, then try calling test server
  293. ; this assures that if a call to the server could not be put through
  294. ;   due to DOS busy, it will be processed immediatly
  295. ;----------------------------------------------------------------------
  296. oldint21    dd    0
  297. semint21    proc    far
  298.         call    _svr0_TestCallSvr
  299.         jmp    cs:[oldint21]
  300. semint21    endp
  301.         
  302. ;----------------------------------------------------------------------
  303. ; if in INT 0x28, we can interrupt DOS if 0 <= SDA_DOSBUSY  <= 1
  304. ;----------------------------------------------------------------------
  305. int28here    db    0
  306. oldint28    dd    0
  307. semint28    proc    far
  308.         inc    cs:[int28here]
  309.         pushf
  310.         call    cs:[oldint28]
  311.         call    _svr0_TestCallSvr
  312.         dec    cs:[int28here]
  313.         iret
  314. semint28    endp
  315.         
  316. ;----------------------------------------------------------------------
  317. ; dos set critical interrupt
  318. ;----------------------------------------------------------------------
  319. oldint2a    dd    0
  320. semint2a    proc    far
  321.         pushf
  322.         cmp    ah,80h        ; entering DOS critical area?
  323.         jnz    @@sem1        ; no, skip
  324.         inc    cs:[doscrit]    ; el